#include "serializer/serializer.h"

#include <gtest/gtest.h>

#include <map>
#include <stack>
#include <string>
#include <vector>

using namespace serializer;

/**
 * 往返序列化工具函数
 * 参数:
 * - value 输入值
 * - options 序列化选项
 * 返回值: 反序列化结果
 */
template <typename T>
T
roundtrip_via_cpo(const T & value, const default_options & options)
{
    vector_writer writer;
    serialize(writer, value, options);
    vector_reader reader(writer.data());
    return deserialize_cpo(reader, options, type_tag<T>);
}

TEST(cpo_edge_cases_test, empty_containers_and_optional_null)
{
    default_options options{};

    std::vector<int> v;
    std::map<int, int> m;
    std::stack<int> st;

    auto v_out = roundtrip_via_cpo(v, options);
    auto m_out = roundtrip_via_cpo(m, options);

    EXPECT_TRUE(v_out.empty());
    EXPECT_TRUE(m_out.empty());

    // optional null
    std::optional<int> onull = std::nullopt;
    auto onull_out = roundtrip_via_cpo(onull, options);
    EXPECT_EQ(onull_out, onull);
}

TEST(cpo_edge_cases_test, container_size_limit_violation_throws)
{
    default_options options{};

    std::vector<int> v(5, 1);
    auto strict = options.with_max_container_size(2);

    vector_writer writer;
    EXPECT_THROW(serialize(writer, v, strict), std::runtime_error);
}

TEST(cpo_edge_cases_test, string_length_limit_violation_throws)
{
    default_options options{};
    std::string s = "hello world";
    auto strict = options.with_max_string_length(3);

    vector_writer writer;
    EXPECT_THROW(serialize(writer, s, strict), std::runtime_error);
}